
package com.hlkj.pay.service.pay.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.hlkj.pay.common.constants.RedisConstants;
import com.hlkj.pay.dto.pay.ProviderQueryDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.infrastructure.mapper.pay.ProviderChannelConfigMapper;
import com.hlkj.pay.infrastructure.mapper.pay.ProviderChannelFeeConfigMapper;
import com.hlkj.pay.infrastructure.mapper.pay.ProviderInfoMapper;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelFeeConfigDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderInfoDO;
import com.hlkj.pay.service.pay.IProviderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;

/**
 * @author HlpayTeam
 * @date 2024/09/23 16:29
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ProviderServiceImpl implements IProviderService {

    private final ProviderInfoMapper providerInfoMapper;

    private final ProviderChannelConfigMapper providerChannelConfigMapper;

    private final ProviderChannelFeeConfigMapper providerChannelFeeConfigMapper;

    @Override
    public PageResult<ProviderInfoDO> queryPage(ProviderQueryDto providerQueryDto) {
        return providerInfoMapper.selectPage(providerQueryDto, buildWrapper(providerQueryDto));
    }

    @Override
    public List<ProviderInfoDO> queryList(ProviderQueryDto providerQueryDto) {
        return providerInfoMapper.selectList(buildWrapper(providerQueryDto));
    }

    @Override
    @Cacheable(value = RedisConstants.PAY_PROVIDER_INFO, key = "#code", unless = "#result == null")
    public ProviderInfoDO queryByCode(String code) {
        ProviderQueryDto providerQueryDto = new ProviderQueryDto();
        providerQueryDto.setCode(code);
        List<ProviderInfoDO> providerInfoList = queryList(providerQueryDto);
        if (CollectionUtils.isEmpty(providerInfoList)) {
            return null;
        }
        return providerInfoList.get(0);
    }

    @Override
    public List<ProviderInfoDO> queryByCodes(List<String> codes) {
        ProviderQueryDto providerQueryDto = new ProviderQueryDto();
        providerQueryDto.setCodes(codes);
        List<ProviderInfoDO> providerInfoList = queryList(providerQueryDto);
        if (CollectionUtils.isEmpty(providerInfoList)) {
            return Collections.emptyList();
        }
        return providerInfoList;
    }

    @Override
    public ProviderInfoDO queryByName(String name) {
        ProviderQueryDto providerQueryDto = new ProviderQueryDto();
        providerQueryDto.setName(name);
        List<ProviderInfoDO> providerInfoList = queryList(providerQueryDto);
        if (CollectionUtils.isEmpty(providerInfoList)) {
            return null;
        }
        return providerInfoList.get(0);
    }

    @Override
    public ProviderInfoDO queryById(Long id) {
        return providerInfoMapper.selectById(id);
    }

    @Override
    public List<ProviderChannelFeeConfigDO> queryEffectFeeConfig(List<String> providerCodes, List<String> channelCodes) {
        LambdaQueryWrapperX<ProviderChannelFeeConfigDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.inIfPresent(ProviderChannelFeeConfigDO::getProviderCode, providerCodes);
        queryWrapper.inIfPresent(ProviderChannelFeeConfigDO::getChannelCode, channelCodes);
        queryWrapper.inIfPresent(ProviderChannelFeeConfigDO::getStatus, CommonEnum.YES_NO_TYPE.YES.getCode());
        return providerChannelFeeConfigMapper.selectList(queryWrapper);
    }

    @Override
    public List<ProviderChannelFeeConfigDO> queryFeeConfig(String providerCode, String channelCode) {
        LambdaQueryWrapperX<ProviderChannelFeeConfigDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(ProviderChannelFeeConfigDO::getProviderCode, providerCode);
        queryWrapper.eqIfPresent(ProviderChannelFeeConfigDO::getChannelCode, channelCode);
        return providerChannelFeeConfigMapper.selectList(queryWrapper);
    }

    @Override
    @Cacheable(value = RedisConstants.PAY_PROVIDER_CONFIG, key = "#providerCode+'_'+#channelCode", unless = "#result == null")
    public ProviderChannelConfigDO queryConfig(String providerCode, String channelCode) {
        LambdaQueryWrapperX<ProviderChannelConfigDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(ProviderChannelConfigDO::getProviderCode, providerCode);
        queryWrapper.eqIfPresent(ProviderChannelConfigDO::getChannelCode, channelCode);
        queryWrapper.last(" limit 1");
        return providerChannelConfigMapper.selectOne(queryWrapper);
    }

    @Override
    public List<ProviderChannelConfigDO> queryConfigList(String providerCode) {
        LambdaQueryWrapperX<ProviderChannelConfigDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(ProviderChannelConfigDO::getProviderCode, providerCode);
        return providerChannelConfigMapper.selectList(queryWrapper);
    }

    @Override
    public List<ProviderChannelConfigDO> queryConfigListByChannel(String channelCode) {
        LambdaQueryWrapperX<ProviderChannelConfigDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(ProviderChannelConfigDO::getChannelCode, channelCode);
        return providerChannelConfigMapper.selectList(queryWrapper);
    }

    @Override
    public void save(ProviderInfoDO providerInfoDO) {
        providerInfoMapper.insert(providerInfoDO);
    }

    @Override
    @CacheEvict(value = RedisConstants.PAY_PROVIDER_INFO, key = "#providerInfoDO.code")
    public void update(ProviderInfoDO providerInfoDO) {
        providerInfoMapper.updateById(providerInfoDO);
    }

    @Override
    @CacheEvict(value = RedisConstants.PAY_PROVIDER_INFO, key = "#code")
    public void delProviderInfo(String code) {
        ProviderQueryDto providerQueryDto = new ProviderQueryDto();
        providerQueryDto.setCode(code);
        providerInfoMapper.delete(buildWrapper(providerQueryDto));
    }

    @Override
    public void saveConfig(ProviderChannelConfigDO providerChannelConfigDO) {
        providerChannelConfigMapper.insert(providerChannelConfigDO);
    }

    @Override
    @CacheEvict(value = RedisConstants.PAY_PROVIDER_CONFIG, key = "#providerChannelConfigDO.providerCode+'_'+#providerChannelConfigDO.channelCode")
    public void updateConfig(ProviderChannelConfigDO providerChannelConfigDO) {
        providerChannelConfigMapper.updateById(providerChannelConfigDO);
    }

    @Override
    @CacheEvict(value = RedisConstants.PAY_PROVIDER_CONFIG, key = "#providerCode+'_'+#channelCode")
    public void delFeeConfig(String providerCode, String channelCode) {
        LambdaQueryWrapperX<ProviderChannelFeeConfigDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(ProviderChannelFeeConfigDO::getProviderCode, providerCode);
        queryWrapper.eqIfPresent(ProviderChannelFeeConfigDO::getChannelCode, channelCode);
        providerChannelFeeConfigMapper.delete(queryWrapper);
    }

    @Override
    public void batchSaveFeeConfig(List<ProviderChannelFeeConfigDO> providerChannelFeeConfigList) {
        providerChannelFeeConfigMapper.insertBatch(providerChannelFeeConfigList);
    }

    /**
     * 查询条件封装
     *
     * @param providerQueryDto
     * @return
     */
    LambdaQueryWrapper<ProviderInfoDO> buildWrapper(ProviderQueryDto providerQueryDto) {
        LambdaQueryWrapperX<ProviderInfoDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(ProviderInfoDO::getCode, providerQueryDto.getCode());
        queryWrapper.inIfPresent(ProviderInfoDO::getCode, providerQueryDto.getCodes());
        queryWrapper.likeIfPresent(ProviderInfoDO::getCode, providerQueryDto.getLikeCode());
        queryWrapper.eqIfPresent(ProviderInfoDO::getName, providerQueryDto.getName());
        queryWrapper.likeIfPresent(ProviderInfoDO::getName, providerQueryDto.getLikeName());
        queryWrapper.eqIfPresent(ProviderInfoDO::getShortName, providerQueryDto.getShortName());
        queryWrapper.likeIfPresent(ProviderInfoDO::getShortName, providerQueryDto.getLikeShortName());
        queryWrapper.eqIfPresent(ProviderInfoDO::getStatus, providerQueryDto.getStatus());
        return queryWrapper;
    }
}
